package cn.lili.modules.promotion.serviceimpl;

import cn.hutool.core.collection.CollUtil;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.security.AuthUser;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.security.enums.SceneEnums;
import cn.lili.common.utils.*;
import cn.lili.common.vo.PageVO;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.member.client.UnionClient;
import cn.lili.modules.member.client.UserClient;
import cn.lili.modules.member.entity.dos.Union;
import cn.lili.modules.operationcenter.client.OperationCenterClient;
import cn.lili.modules.operationcenter.entity.dos.OperationCenter;
import cn.lili.modules.operationcenter.entity.dos.OperationCenterWithdrawal;
import cn.lili.modules.order.order.entity.vo.UnionMonthFundsVO;
import cn.lili.modules.order.order.entity.vo.UnionOrderParams;
import cn.lili.modules.payment.entity.enums.WithdrawStatusEnum;
import cn.lili.modules.promotion.entity.dos.GreenConfig;
import cn.lili.modules.promotion.entity.dos.GreenContributionInfo;
import cn.lili.modules.promotion.entity.dos.GreenCount;
import cn.lili.modules.promotion.entity.dto.GreenConfigValueDTO;
import cn.lili.modules.promotion.entity.enums.GreenAmountInfoStatusEnum;
import cn.lili.modules.promotion.entity.enums.GreenAmountInfoTypeEnum;
import cn.lili.modules.promotion.entity.vos.GreenContributionInfoViewVO;
import cn.lili.modules.promotion.entity.vos.GreenPointStatistic;
import cn.lili.modules.promotion.mapper.GreenContributionInfoMapper;
import cn.lili.modules.promotion.service.*;
import cn.lili.mybatis.util.PageUtil;
import com.alibaba.fastjson.JSONObject;
import com.api.PayApi;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pojos.GmoneyResUser;
import com.pojos.UserRes;
import io.swagger.annotations.ApiModelProperty;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.transaction.annotation.ShardingTransactionType;
import org.apache.shardingsphere.transaction.core.TransactionType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author xiangqian
 * @version 1.0
 * @data 2023/12/18 14:17
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class GreenContributionInfoServiceImpl extends ServiceImpl<GreenContributionInfoMapper, GreenContributionInfo> implements GreenContributionInfoService {

    private final GreenConfigService greenConfigService;
    private final GreenCountService greenCountService;
    private final GreenPoolService greenPoolService;
    private final GreenUnitPriceService greenUnitPriceService;
    private final PayApi payApi;

    private final UnionClient unionClient;

    private final OperationCenterClient operationCenterClient;

    private final UserClient userClient;

    /**
     * 分页查询贡献值明细
     *
     * @param greenContributionInfo 查询条件{@link GreenContributionInfo}
     * @param page                  分页条件{@link PageVO}
     * @return 分页返回结果
     */
    @Override
    public Page<GreenContributionInfo> infoPage(GreenContributionInfo greenContributionInfo, PageVO page) {
        Page<GreenContributionInfo> resultPage = this.baseMapper.selectPage(PageUtil.initPage(page), greenContributionInfo.queryWrapperPage());
        List<GreenContributionInfo> resultList = resultPage.getRecords();

        return resultPage.setRecords(resultList.stream().peek(e->{
            e.setTypeValue(GreenAmountInfoTypeEnum.valueOf(e.getType()).description());
            e.setStatusValue(GreenAmountInfoStatusEnum.valueOf(e.getStatus()).description());
        }).collect(Collectors.toList()));
    }

    /**
     * 分页查询绿色积分(绿色积分管理-用户)
     *
     * @param gmoneyResUser 查询条件{@link GmoneyResUser}
     * @param page          分页条件{@link PageVO}
     * @return 分页返回结果
     */
    @Override
    public Page<GmoneyResUser> greenPage(GmoneyResUser gmoneyResUser, PageVO page) {
        Page<GmoneyResUser> resultPage = new Page<>();
        log.info("gmoneyResUser----{}",gmoneyResUser);
        JSONObject jsonObject = payApi.allUserGmoneys(gmoneyResUser.getUid(), page.getPageNumber(), page.getPageSize(), null, null);
        log.info("jsonObject----{}",jsonObject);
        if (jsonObject.getInteger("code") == 200) {
            String data = jsonObject.getString("data");
            String count = jsonObject.getString("count");
            List<GmoneyResUser> list = gmoneyResUser.initGmoneyResUser(data);
            resultPage.setTotal(Integer.parseInt(count));
            resultPage.setRecords(list);
        }

        resultPage.setPages(page.getPageNumber());
        resultPage.setSize(page.getPageSize());
        return resultPage;
    }

    /**
     * 添加待结算贡献值/绿色积分
     *
     * @param greenContributionInfo 添加数据{@link GreenContributionInfo}
     * @return 返回结果
     */
    @Override
    @Transactional
    @ShardingTransactionType(TransactionType.BASE)
    public Boolean saveSettle(GreenContributionInfo greenContributionInfo) {
        //添加待结算贡献值/绿色积分
        return this.save(greenContributionInfo);
    }

    /**
     * 添加结算贡献值/绿色积分
     *
     * @param orderSn 子订单ID
     * @return 返回结果
     */
    @Override
    @Transactional
    @ShardingTransactionType(TransactionType.BASE)
    public Boolean settle(String orderSn,String userId) {
        //查询功能配置
        GreenConfig greenConfig = greenConfigService.getNewConfig();
        Assert.notNull(greenConfig, "功能配置不存在");
        Assert.notNull(greenConfig.getConfigValue(), "贡献值配置不存在");
        GreenConfigValueDTO greenConfigValueDTO = JSONObject.parseObject(greenConfig.getConfigValue(), GreenConfigValueDTO.class);

        //查询最新单价
        BigDecimal newUnitPrice = greenUnitPriceService.getNewUnitPrice();

        GreenContributionInfo queryGreenContributionInfo = new GreenContributionInfo();
        queryGreenContributionInfo.setOrderSn(orderSn);
        queryGreenContributionInfo.setUserId(userId);
        queryGreenContributionInfo.setStatus(GreenAmountInfoStatusEnum.TO_BE_SETTLED.name());
        List<GreenContributionInfo> greenContributionInfoList = this.getBaseMapper().selectList(queryGreenContributionInfo.queryWrapperPage());
        for (GreenContributionInfo greenContributionInfo:greenContributionInfoList) {
            //计算贡献值
            BigDecimal outputratio = new BigDecimal(greenConfigValueDTO.getOutputratio());
            BigDecimal tempOutputratio = outputratio.divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
            BigDecimal newUmber = tempOutputratio.multiply(greenContributionInfo.getScoreNumber()).divide(newUnitPrice,10,RoundingMode.HALF_UP);
            greenContributionInfo.setUmber(newUmber);

            //增加实时统计
            GreenCount queryGreenCount = new GreenCount();
            queryGreenCount.setUserId(greenContributionInfo.getUserId());
            GreenCount greenCount = greenCountService.getBaseMapper().selectOne(queryGreenCount.queryWrapperPage());
            if (greenCount == null) {
                greenCount = new GreenCount();
                BeanUtil.copyProperties(greenContributionInfo, greenCount);
                greenCountService.save(greenCount);
            } else {
                greenCount.setUmber(greenContributionInfo.getUmber().add(greenCount.getUmber()));
                greenCountService.updateById(greenCount);
            }

            //增加绿色积分池
            greenPoolService.addGreenPool(greenContributionInfo.getScoreNumber());

            //修改贡献值状态
            greenContributionInfo.setStatus(GreenAmountInfoStatusEnum.INCOME.name());
            //更改后余额
            greenContributionInfo.setAfterBalance(greenCount.getUmber());

            this.updateById(greenContributionInfo);
        }
        return true;
    }

    @Override
    public Boolean settleDirect(String orderSn, String userId,String status) {
        GreenContributionInfo queryGreenContributionInfo = new GreenContributionInfo();
        queryGreenContributionInfo.setOrderSn(orderSn);
        queryGreenContributionInfo.setUserId(userId);
        queryGreenContributionInfo.setStatus(GreenAmountInfoStatusEnum.TO_BE_SETTLED.name());
        List<GreenContributionInfo> greenContributionInfoList = this.getBaseMapper().selectList(queryGreenContributionInfo.queryWrapperPage());
        for (GreenContributionInfo greenContributionInfo:greenContributionInfoList) {
            //修改贡献值状态
            greenContributionInfo.setStatus(status);
            this.updateById(greenContributionInfo);

            if (!status.equals(GreenAmountInfoStatusEnum.CANCELLED.name())) {
                if (SceneEnums.OPERATION_CENTER.name().equals(greenContributionInfo.getUserType())) {
                    // 记录绿色积分变动记录
                    OperationCenterWithdrawal operationCenterWithdrawal = new OperationCenterWithdrawal();
                    OperationCenter operationCenter = operationCenterClient.getOperationCenter(userId);
                    operationCenterWithdrawal.setOperationId(operationCenter.getId());
                    operationCenterWithdrawal.setUserId(operationCenter.getUserId());
                    operationCenterWithdrawal.setOperationName(operationCenter.getOperationName());
                    operationCenterWithdrawal.setMoney(Double.valueOf(String.valueOf(greenContributionInfo.getScoreNumber())));
                    operationCenterWithdrawal.setRemarks(orderSn + "-订单分佣打款");
                    operationCenterWithdrawal.setOrderNo(SnowFlake.createStr("DH"));
                    operationCenterWithdrawal.setStatus(WithdrawStatusEnum.VIA_AUDITING.name());
                    operationCenterWithdrawal.setGreenScoreType(GreenAmountInfoStatusEnum.INCOME.name());
                    UserRes userRes = payApi.getUserMoney(userClient.getById(operationCenter.getUserId()).getOpenId());
                    Double beforeMoney = CurrencyUtil.div(Double.parseDouble(userRes.getGmoney()), 100);
                    operationCenterWithdrawal.setBeforeMoney(CurrencyUtil.sub(beforeMoney,Double.parseDouble(String.valueOf(greenContributionInfo.getScoreNumber()))));
                    Double afterMoney = CurrencyUtil.add(operationCenterWithdrawal.getBeforeMoney(), Double.parseDouble(String.valueOf(greenContributionInfo.getScoreNumber())));
                    operationCenterWithdrawal.setAfterMoney(afterMoney);
                    operationCenterClient.insertWithdrawal(operationCenterWithdrawal);
                }
            }

        }
        return true;
    }


    /**
     * 工会贡献值明细
     * @param info
     * @param pagevo
     * @return
     */
    @Override
    public Page<GreenContributionInfoViewVO> getUnionContributeDetails(GreenContributionInfo info, PageVO pagevo) {
        QueryWrapper queryWrapper =  new QueryWrapper();
        //UserRes userRes = payApi.getUserMoney(Objects.requireNonNull(UserContext.getCurrentUser()).getOpenId());
        queryWrapper.eq("info.status", info.getStatus());
        queryWrapper.eq("info.type", info.getType());
        queryWrapper.eq("info.user_id", Objects.requireNonNull(UserContext.getCurrentUser()).getId());
        queryWrapper.eq("info.user_type", SceneEnums.OPERATION_CENTER.name());
        queryWrapper.orderByDesc("info.create_time");
        //        //收入支出
//        info.setStatus(GreenAmountInfoStatusEnum.INCOME.name());
        Page<GreenContributionInfoViewVO> page = baseMapper.getUnionContributeDetails(queryWrapper, new Page<>(pagevo.getPageNumber(), pagevo.getPageSize()));
        if (page != null && CollUtil.isNotEmpty(page.getRecords())) {
            //遍历
            page.getRecords().stream().forEach(e->{
                if (e.getAfterBalance() != null) {
                    if (info.getStatus().equals(GreenAmountInfoStatusEnum.INCOME.name())) {
                        e.setBeforeBalance(e.getAfterBalance() - e.getUmber() > 0 ? e.getAfterBalance() - e.getUmber() : 0);
                        if (StringUtils.isNotEmpty(e.getUnionId())) {
                            Union union = unionClient.getById(e.getUnionId());
                            if (null != union) {
                                e.setUnionName(union.getUnionName() + "-订单收益结算");
                            }else {
                                e.setUnionName("订单收益结算");
                            }
                        }else {
                            e.setUnionName("订单收益结算");
                        }
                    }else if (info.getStatus().equals(GreenAmountInfoStatusEnum.DISBURSE.name())) {
                        e.setBeforeBalance(e.getAfterBalance() + e.getUmber() > 0 ? e.getAfterBalance() + e.getUmber() : 0);
                        OperationCenter operationCenter = operationCenterClient.getOperationCenter(e.getUserId());
                        if (null != operationCenter) {
                            e.setUnionName(operationCenter.getOperationName() + "-兑换绿色积分");
                        }else {
                            e.setUnionName("兑换绿色积分");
                        }
                    }
                }
            });
        }
        return page;
    }


    /**
     * 绿色积分，贡献值统计
     * @param info
     * @return
     */
    @Override
    public ResultMessage<GreenPointStatistic> greenPointStatisticUnsettle(GreenContributionInfo info) {
        AuthUser authUser = UserContext.getCurrentUser();
        log.info("#greenPointStatisticUnsettle# 绿色积分，贡献值统计 , authUser,{}", JSONObject.toJSONString(authUser));
        if (authUser == null) {
            return ResultUtil.error(400, "未登陆");
        }
        GreenPointStatistic statistic = new GreenPointStatistic();
        //查询我的绿色积分
        UserRes userRes = payApi.getUserMoney(authUser.getOpenId());
        log.info("#greenPointStatisticUnsettle# 查询我的绿色积分 , userRes,{}", JSONObject.toJSONString(userRes));
        if (userRes != null && userRes.getGmoney() != null) {
            BigDecimal moneyDecimal = new BigDecimal(userRes.getGmoney());
            moneyDecimal = moneyDecimal.divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
            statistic.setGreenMoney(moneyDecimal.doubleValue());
        }
        //查询我的绿色贡献值
        Double userContributionAllValue = greenCountService.getContributionAllValueByUserId(authUser.getId());
        log.info("#greenPointStatisticUnsettle# 查询我的绿色贡献值,{}", userContributionAllValue);
        statistic.setGreenContibute(userContributionAllValue);
        //查询我的待结算绿色积分
        Double userContributionAllValueStay = greenCountService.getSettleUmberByUserId(authUser.getId());
        log.info("#greenPointStatisticUnsettle# 查询我的待结算绿色积分,{}", userContributionAllValueStay);
        statistic.setGreenMoneyUnsettle(userContributionAllValueStay);
        //查询最新单价
        BigDecimal newUnitPrice = greenUnitPriceService.getNewUnitPrice();
        log.info("#greenPointStatisticUnsettle# 查询最新单价,{}", newUnitPrice);
        statistic.setNewUnitPrice(newUnitPrice.doubleValue());
        //查询待结算的绿色贡献值
        info.setStatus(GreenAmountInfoStatusEnum.TO_BE_SETTLED.name());
        info.setUserId(authUser.getId());
        info.setType(GreenAmountInfoTypeEnum.AUTO_DIVIDEND.name());
        Double sumContributeSettle = baseMapper.getSumContributeSettle(info);
        log.info("#greenPointStatisticUnsettle# 查询待结算的绿色贡献值,{}", sumContributeSettle);
        statistic.setGreenContibuteUnsettle(sumContributeSettle);
        log.info("#greenPointStatisticUnsettle# 最后反回对象:{}", JSONObject.toJSONString(statistic));
        return ResultUtil.data(statistic);
    }

    @Override
    public Page<UnionMonthFundsVO> getSumContributeSettleByUnion(UnionOrderParams params) {
        return baseMapper.getSumContributeSettleByUnion(PageUtil.initPage(params), params.getUnionId());
    }

}
